﻿#region Using Statemens
using System;
using GameBase.Screens;
using GameBase.Sprites;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StarFox.ScreenComponents;
#endregion

namespace StarFox.Screens
{
    /// <summary>
    /// Presentation screen of the game.
    /// </summary>
    public class PresentationScreen : StarFoxScreen
    {
        #region Screen Transitions

        // indicates whether this screen is first shown
        bool isFirstShown = true;

        /// <summary>
        /// Makes the Screen transition to visible state.
        /// </summary>
        public override void Show()
        {
            // if first shown, play the playlist
            if (isFirstShown)
            {
                string[] playList = { "01_MENU_THEME" };
                PlayList.Start(playList);
                PlayList.Repeat = true;

                isFirstShown = false;
            }

            base.Show();
        }

        #endregion

        #region Initialization

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="screenManager">The ScreenManager that this Screen is associated to.</param>
        public PresentationScreen(ScreenManager screenManager)
            : base(screenManager)
        {
            Name = "PresentationScreen";
        }

        /// <summary>
        /// Called when the Screen needs to be initialized.
        /// </summary>
        public override void Initialize()
        {
            Components3D.Add(new MenuBackground(this) { Duration = TimeSpan.FromSeconds(6) });

            Components2D.Add(new StarFoxLogo(this));
            Components2D.Add(new PresentationMessage(this));

            base.Initialize();
        }

        #endregion
    }

    #region StarFox Logo

    /// <summary>
    /// StarFox logo.
    /// </summary>
    public class StarFoxLogo : ScreenComponent2D
    {
        #region Fields

        // sprite sheet
        SpriteSheet spriteSheet;

        // starfox title
        Rectangle dstRectStarFox;
        Point initPosStarFox;
        Point endPosStarFox;

        // xna title
        Rectangle dstRectXna;
        Point initPosXna;
        Point endPosXna;

        #endregion

        #region Screen Transitions

        bool toVisible = false;
        bool toHidden = false;

        float trTime = 0.0f;

        /// <summary>
        /// Makes the ScreenComponent2D transition to visible state.
        /// </summary>
        public override void Show()
        {
            toVisible = true;
        }

        /// <summary>
        /// Makes the ScreenComponent2D transition to hidden state.
        /// </summary>
        public override void Hide()
        {
            toHidden = true;
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="screen">The Screen that this ScreenComponent2D is associated to.</param>
        public StarFoxLogo(StarFoxScreen screen)
            : base(screen)
        {
            // asset loading
            spriteSheet = Game.Content.Load<SpriteSheet>(ContentSettings.GetAsset("MENU_SPRITES"));

            // starfox title
            Rectangle auxRect = spriteSheet.SourceRectangle("LOGO_STARFOX_BIG");
            dstRectStarFox = new Rectangle(0, 0, (int)(auxRect.Width * Screen.Scale), (int)(auxRect.Height * Screen.Scale));
            initPosStarFox = new Point((int)((Screen.Width - dstRectStarFox.Width) * 0.5f), -dstRectStarFox.Height);
            endPosStarFox = new Point(initPosStarFox.X, (int)(Screen.Height * 0.3f));
            dstRectStarFox.Location = initPosStarFox;

            // xna title
            auxRect = spriteSheet.SourceRectangle("LOGO_XNA_BIG");
            dstRectXna = new Rectangle(0, 0, (int)(auxRect.Width * Screen.Scale), (int)(auxRect.Height * Screen.Scale));
            initPosXna = new Point(Screen.Width, (int)(Screen.Height * 0.45f));
            endPosXna = new Point((int)((Screen.Width + dstRectStarFox.Width) * 0.5f - dstRectXna.Width), initPosXna.Y);
            dstRectXna.Location = initPosXna;
        }

        #endregion

        #region Update

        /// <summary>
        /// Called when the ScreenComponent2D needs to be updated.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to this method.</param>
        public override void Update(GameTime gameTime)
        {
            #region Screen Transition

            if (toVisible)
            {
                // update item positions
                float auxTrTime = 1.0f - (float)Math.Pow(1.0f - trTime, 2);
                dstRectStarFox.Y = initPosStarFox.Y + (int)(Math.Abs(initPosStarFox.Y - endPosStarFox.Y) * auxTrTime);
                dstRectXna.X = initPosXna.X - (int)(Math.Abs(initPosXna.X - endPosXna.X) * auxTrTime);

                // update transition timer
                float trDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / Time.TotalMilliseconds);
                trTime += trDelta;
                trTime = MathHelper.Clamp(trTime, 0.0f, 1.0f);
                if (trTime == 1.0f) { toVisible = false; trTime = 0.0f; }
            }
            else if (toHidden)
            {
                // update item positions
                float auxTrTime = (float)Math.Pow(trTime, 2);
                dstRectStarFox.Y = endPosStarFox.Y - (int)(Math.Abs(initPosStarFox.Y - endPosStarFox.Y) * auxTrTime);
                dstRectXna.X = endPosXna.X + (int)(Math.Abs(initPosXna.X - endPosXna.X) * auxTrTime);

                // update transition timer
                float trDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / Time.TotalMilliseconds);
                trTime += trDelta;
                trTime = MathHelper.Clamp(trTime, 0.0f, 1.0f);
                if (trTime == 1.0f) { toHidden = false; trTime = 0.0f; }
            }

            #endregion
        }

        #endregion

        #region Draw

        /// <summary>
        /// Called when the ScreenComponent2D needs to be drawn.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to this method.</param>
        public override void Draw(GameTime gameTime)
        {
            // starfox title
            SpriteBatch.Draw(spriteSheet.Texture, dstRectStarFox, spriteSheet.SourceRectangle("LOGO_STARFOX_BIG"), Color.Red);

            // xna title
            SpriteBatch.Draw(spriteSheet.Texture, dstRectXna, spriteSheet.SourceRectangle("LOGO_XNA_BIG"), Color.Red);
        }

        #endregion
    }

    #endregion

    #region Presentation Message

    /// <summary>
    /// Presentation message.
    /// </summary>
    public class PresentationMessage : ScreenComponent2D
    {
        #region Fields

        // sprite font
        SpriteFont messageFont;

        // presentation message
        Vector2 posMessage;

        // flashing effect
        float messageAlpha = 1.0f;
        bool toInvisible = true;
        TimeSpan totalFadeTime = TimeSpan.FromMilliseconds(500);
        float fadeTime = 0.0f;

        // player index
        PlayerIndex playerIndex;

        #endregion

        #region Screen Transitions

        /// <summary>
        /// Makes the ScreenComponent2D transition to visible state.
        /// </summary>
        public override void Show()
        {
            // make the message transition to visible when the screen is showing
            messageAlpha = 0.0f;
            toInvisible = false;
            fadeTime = 0.0f;
        }

        /// <summary>
        /// Makes the ScreenComponent2D transition to hidden state.
        /// </summary>
        public override void Hide()
        {
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="screen">The Screen that this ScreenComponent2D is associated to.</param>
        public PresentationMessage(StarFoxScreen screen)
            : base(screen)
        {
            // asset loading
            messageFont = Game.Content.Load<SpriteFont>(ContentSettings.GetAsset("FONT_BIG"));

            // message
            Vector2 auxStrSize = messageFont.MeasureString("PRESS START");
            posMessage = new Vector2((Screen.Width - auxStrSize.X * Screen.Scale) * 0.5f, Screen.Height * 0.7f);
        }

        #endregion

        #region Update

        /// <summary>
        /// Called when the ScreenComponent2D needs to be updated.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to this method.</param>
        public override void Update(GameTime gameTime)
        {
            #region Player Input

            if (Screen.InputEnabled)
            {
                // press start
                if (Screen.PlayerInput.IsMenuPressStart(out playerIndex))
                {
                    Screen.PlayerIndex = playerIndex;
                    Screen.ScreenSound.Enter();
                    Screen.ScreenManager.AddScreen(new MainMenuScreen(Screen.ScreenManager));
                }
            }

            #endregion

            #region Flashing Message

            if (toInvisible)
            {
                float fadeDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / totalFadeTime.TotalMilliseconds);
                fadeTime += fadeDelta;
                fadeTime = MathHelper.Clamp(fadeTime, 0.0f, 1.0f);
                messageAlpha = (float)Math.Pow(1.0f - fadeTime, 2);
                if (fadeTime == 1.0f) { toInvisible = false; fadeTime = 0.0f; }
            }
            else
            {
                float fadeDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / totalFadeTime.TotalMilliseconds);
                fadeTime += fadeDelta;
                fadeTime = MathHelper.Clamp(fadeTime, 0.0f, 1.0f);
                messageAlpha = (float)Math.Pow(fadeTime, 2);
                if (fadeTime == 1.0f) { toInvisible = true; fadeTime = 0.0f; }
            }

            #endregion
        }

        #endregion

        #region Draw

        /// <summary>
        /// Called when the ScreenComponent2D needs to be drawn.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to this method.</param>
        public override void Draw(GameTime gameTime)
        {
            SpriteBatch.DrawString(messageFont, "PRESS START", posMessage, Color.Red * messageAlpha, 0, Vector2.Zero, Screen.Scale, SpriteEffects.None, 0);
        }

        #endregion
    }

    #endregion
}